import pandas as pd
from datetime import datetime
import os
import re
import json
import random

def convert_excel_timestamp(file_path, output_path=None):
    """
    将Kafka工具导出的Excel文件中的时间戳转换为北京时间，并提取特定字段
    
    参数:
    file_path: 输入的Excel文件路径
    output_path: 输出的Excel文件路径，默认为在原文件名后加"_converted"
    """
    
    try:
        # 读取Excel文件，没有标题行
        df = pd.read_excel(file_path, header=None)
        
        # 检查DataFrame是否为空
        if df.empty:
            print(f"文件 {file_path} 是空的或无法读取")
            return
        
        print(f"成功读取文件 {file_path}，共有 {len(df)} 行数据")
        
        # 设置列名
        # 确保列数足够，如果不足则添加缺失的列
        column_count = len(df.columns)
        if column_count >= 5:
            df.columns = ['Partition', 'Offset', 'Key', 'Value', 'Timestamp'] + [f'Column_{i}' for i in range(5, column_count)]
        else:
            # 如果列数不足5列，则只设置现有列数的名称
            column_names = ['Partition', 'Offset', 'Key', 'Value', 'Timestamp']
            df.columns = column_names[:column_count] + [f'Column_{i}' for i in range(column_count, 5)]
            # 添加缺失的列
            for i in range(column_count, 5):
                df[f'Column_{i}'] = None
        
        # 只保留需要的列，Value列需要进一步处理
        # 确保所需的列存在
        required_columns = ['Value', 'Timestamp']
        available_columns = [col for col in required_columns if col in df.columns]
        if len(available_columns) < len(required_columns):
            missing_columns = set(required_columns) - set(available_columns)
            print(f"警告: 文件缺少以下列: {missing_columns}")
            
        df_selected = df[available_columns].copy() if available_columns else pd.DataFrame()
        
        if df_selected.empty:
            print(f"警告: 无法从文件 {file_path} 中提取所需的数据列")
            return
        
        # 解析Value列中的数据并提取所需字段
        def parse_value(value):
            try:
                cid = ''
                sip = ''
                spt = ''
                dip = ''
                dpt = ''
                http_request_line = ''
                
                # 如果是字符串，尝试解析
                if isinstance(value, str):
                    # 提取cid
                    cid_match = re.search(r'"cid"[\'"\s:]+([^\'"\s,}]+)', value)
                    if cid_match:
                        cid = cid_match.group(1)
                    
                    # 提取sip
                    sip_match = re.search(r'"sip"[\'"\s:]+([^\'"\s,}]+)', value)
                    if sip_match:
                        sip = sip_match.group(1)
                    
                    # 提取spt
                    spt_match = re.search(r'"spt"[\'"\s:]+(\d+)', value)
                    if spt_match:
                        spt = spt_match.group(1)
                    
                    # 提取dip
                    dip_match = re.search(r'"dip"[\'"\s:]+([^\'"\s,}]+)', value)
                    if dip_match:
                        dip = dip_match.group(1)
                    
                    # 提取dpt
                    dpt_match = re.search(r'"dpt"[\'"\s:]+(\d+)', value)
                    if dpt_match:
                        dpt = dpt_match.group(1)
                    
                    # 提取HTTP请求行（第一行）
                    # HTTP请求的第一行通常是: OPTIONS /path HTTP/1.1
                    # 先查找OPTIONS请求
                    options_match = re.search(r'^OPTIONS\s+(\S+)\s+(HTTP/\d\.\d)', value, re.MULTILINE)
                    if options_match:
                        http_request_line = f"OPTIONS {options_match.group(1)} {options_match.group(2)}"
                    else:
                        # 查找其他HTTP方法
                        http_match = re.search(r'^(GET|POST|PUT|DELETE|HEAD|PATCH)\s+(\S+)\s+(HTTP/\d\.\d)', value, re.MULTILINE)
                        if http_match:
                            http_request_line = f"{http_match.group(1)} {http_match.group(2)} {http_match.group(3)}"
                        else:
                            # 如果以上都没有找到，尝试从Header中提取
                            header_match = re.search(r'Header: \{.*?"cid"[^}]*\}', value)
                            if header_match:
                                header_content = header_match.group(0)
                                # 从Header中提取HTTP方法和路径
                                method_match = re.search(r'"method"\s*:\s*"([A-Z]+)"', header_content)
                                path_match = re.search(r'"path"\s*:\s*"([^"]+)"', header_content)
                                version_match = re.search(r'"version"\s*:\s*"([A-Z\/\d\.]+)"', header_content)
                                
                                if method_match and path_match and version_match:
                                    http_request_line = f"{method_match.group(1)} {path_match.group(1)} {version_match.group(1)}"
                                elif method_match and path_match:
                                    http_request_line = f"{method_match.group(1)} {path_match.group(1)} HTTP/1.1"
                                elif method_match and version_match:
                                    http_request_line = f"{method_match.group(1)} / {version_match.group(1)}"
                                elif method_match:
                                    http_request_line = f"{method_match.group(1)} / HTTP/1.1"
                            else:
                                # 最后尝试从整个文本中查找HTTP请求行
                                http_line_match = re.search(r'(GET|POST|PUT|DELETE|HEAD|OPTIONS|PATCH)\s+[^\n]+\s+HTTP/\d\.\d', value)
                                if http_line_match:
                                    http_request_line = http_line_match.group(0)
                
                return pd.Series([cid, sip, spt, dip, dpt, http_request_line])
            except Exception as e:
                print(f"解析Value时出错: {e}")
                return pd.Series(['', '', '', '', '', ''])

        # 应用解析函数
        parsed_data = df_selected['Value'].apply(parse_value) if 'Value' in df_selected.columns else pd.DataFrame()
        if not parsed_data.empty:
            df_selected[['cid', 'sip', 'spt', 'dip', 'dpt', 'http_request_line']] = parsed_data
        
        # 转换时间戳为北京时间
        def timestamp_to_bj_time(timestamp):
            try:
                # 根据时间戳长度判断是秒还是毫秒
                if len(str(int(timestamp))) > 10:
                    # 毫秒级时间戳
                    bj_time = datetime.fromtimestamp(timestamp/1000).strftime('%Y-%m-%d %H:%M:%S')
                else:
                    # 秒级时间戳
                    bj_time = datetime.fromtimestamp(timestamp).strftime('%Y-%m-%d %H:%M:%S')
                return bj_time
            except Exception as e:
                return str(timestamp)  # 如果转换失败，返回原始值
        
        # 应用转换函数
        if 'Timestamp' in df_selected.columns:
            df_selected['Beijing_Time'] = df_selected['Timestamp'].apply(timestamp_to_bj_time)
        
        # 只保留需要的列
        columns_to_keep = ['cid', 'sip', 'spt', 'dip', 'dpt', 'http_request_line', 'Beijing_Time']
        existing_columns = [col for col in columns_to_keep if col in df_selected.columns]
        result_df = df_selected[existing_columns] if existing_columns else pd.DataFrame()
        
        if result_df.empty:
            print(f"警告: 无法从文件 {file_path} 中提取有效数据")
            return
        
        # 确定输出路径
        if output_path is None:
            # 生成文件名，使用kaf前缀，后跟日期和随机数字
            current_date = datetime.now().strftime('%m%d')
            random_number = random.randint(1000, 9999)
            # 确保文件保存到指定目录 D:\DPI测试\转储测试\Data
            output_dir = r"D:\DPI测试\转储测试\Data"
            output_path = os.path.join(output_dir, f"kaf_{current_date}_{random_number}.xlsx")
        
        # 保存到新的Excel文件
        result_df.to_excel(output_path, index=False)
        print(f"转换完成，文件已保存到: {output_path}")
        print(f"提取的数据示例:")
        print(result_df.head())
        
    except Exception as e:
        print(f"处理文件 {file_path} 时出错: {e}")
        import traceback
        traceback.print_exc()

def main():
    # 使用正则表达式查找并处理目录中的所有数字命名的xlsx文件
    data_dir = r"D:\DPI测试\转储测试\Data"
    
    # 查找目录中所有符合数字命名规则的xlsx文件
    pattern = re.compile(r'^(\d+)\.xlsx$')
    xlsx_files = [f for f in os.listdir(data_dir) if pattern.match(f)]
    
    if not xlsx_files:
        print(f"在目录 {data_dir} 中未找到数字命名的xlsx文件")
        return
    
    # 按数字顺序排序文件
    xlsx_files.sort(key=lambda x: int(pattern.match(x).group(1)))
    
    print(f"找到以下数字命名的xlsx文件: {xlsx_files}")
    
    # 处理每个找到的文件
    for filename in xlsx_files:
        input_file = os.path.join(data_dir, filename)
        print(f"\n正在处理文件: {input_file}")
        
        # 检查输入文件是否存在
        if os.path.exists(input_file):
            convert_excel_timestamp(input_file, None)  # output_path设为None，让函数自动生成文件名
        else:
            print(f"输入文件不存在: {input_file}")

if __name__ == "__main__":
    main()